﻿using System;
using System.Security.Cryptography;
using System.Text;

namespace LAPI.Core.Helpers
{
    public class Cryptographer
    {
        /// <summary>
        /// Crear semilla para encriptar una cadena con 64 bits.
        /// </summary>
        /// <returns>cadena con la semilla, que es una cadena en base64 con el valor de un número aleatorio</returns>
        public static String CreateSeed()
        {
            int size = 64;
            //Genera el servicio con un número aleatorio
            var rng = new RNGCryptoServiceProvider();
            var buff = new byte[size];
            rng.GetBytes(buff);
            // Return a Base64 string representation of the random number.
            return Convert.ToBase64String(buff);
        }


        /// <summary>
        /// Crea un hash para una contraseña
        /// </summary>
        /// <param name="password">contraseña</param>
        /// <param name="seed">semilla</param>
        /// <returns>cadena con el hash, que es una cadena en base64 con el valor de la cadena password+seed</returns>
        public static String GetPasswordHash(String password, String seed)
        {
            return ComputeHash(password + seed);
        }


        /// <summary>
        /// Crea un hash para la contraseña, basado en una contraseña y la semilla(Seed)
        /// </summary>
        /// <param name="valueToHash">valor para convertir a base64</param>
        /// <returns>cadena con el hash, que es una cadena en base64 con el valor de la cadena pasada</returns>
        private static String ComputeHash(String valueToHash)
        {
            HashAlgorithm algorithm = SHA512.Create();
            byte[] hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(valueToHash));
            return Convert.ToBase64String(hash);
        }


        /// <summary>
        /// Encriptar una cadena en base64.
        /// </summary>
        /// <param name="message">cadena a cifrar</param>
        /// <param name="key">algoritmo o semilla usada. Es un parámetro de salida que se genera durante el cifrado.</param>
        /// <returns>Cadena cifrada</returns>
        public static String EncryptAndGenerateKey(String message, out String key)
        {
            try
            {
                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                key = Convert.ToBase64String(des.Key);
                des.Mode = CipherMode.ECB;
                ICryptoTransform encryptor = des.CreateEncryptor();
                byte[] data = Encoding.Unicode.GetBytes(message);
                byte[] dataEncrypted = encryptor.TransformFinalBlock(data, 0, data.Length);
                return Convert.ToBase64String(dataEncrypted);
            }
            catch
            {
                key = String.Empty;
                return String.Empty;
            }
        }


        /// <summary>
        /// Encriptar una cadena en base64.
        /// </summary>
        /// <param name="message">cadena a cifrar</param>
        /// <param name="key">algoritmo o semilla usada.</param>
        /// <returns>Cadena cifrada</returns>
        public static String Encrypt(String message, String key)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            des.Key = Convert.FromBase64String(key);
            des.Mode = CipherMode.ECB;
            ICryptoTransform encryptor = des.CreateEncryptor();
            byte[] data = Encoding.Unicode.GetBytes(message);
            byte[] dataEncrypted = encryptor.TransformFinalBlock(data, 0, data.Length);
            return Convert.ToBase64String(dataEncrypted);
        }


        /// <summary>
        /// Desencriptar una cadena en base64.
        /// </summary>
        /// <param name="message">cadena a descifrar</param>
        /// <param name="key">algoritmo o semilla usada.</param>
        /// <returns>Cadena descifrada</returns>
        public static string Decrypt(String message, String key)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            des.Key = Convert.FromBase64String(key);
            des.Mode = CipherMode.ECB;
            ICryptoTransform decryptor = des.CreateDecryptor();
            byte[] data = Convert.FromBase64String(message);
            byte[] dataDecrypted = decryptor.TransformFinalBlock(data, 0, data.Length);
            return Encoding.Unicode.GetString(dataDecrypted);
        }
    }
}
